package com.example.controller.qiniu.oos.client.upload;

import com.example.controller.qiniu.oos.server.upload.UploadLocalFile;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.qiniu.util.Auth;
import com.qiniu.util.StringMap;
import com.qiniu.util.UrlSafeBase64;
import com.sun.deploy.net.URLEncoder;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * 客户端文件上传
 *
 * @author xiaoming
 * @version 1.0
 * @date 2019-06-02 15:05
 **/
@Controller
@RequestMapping(value = "/upload")
public class UploadController {
    // 测试 AK,SK
    private static String accessKey = "xxdTwX3v2X1c8ml-xwFD7saUIW3fWALhoQuByre-";
    private static String secretKey = "-LoCyCeUJOOUIuAqm4ncbMn-5onjgBCyzCoTVpbm";
    // 测试 bucket
    private static String bucket = "filestoragetest";
    // 测试域名(ngrok)
    private static String hostname = "http://qiniuoostest.free.idcfengye.com";
    // 七牛融合 CDN 测试域名
    private static String domainOfBucket = "http://pse727wzu.bkt.clouddn.com";

    private static Log log = LogFactory.getLog(UploadLocalFile.class);

    /**
     * 获取上传凭证
     */
    @RequestMapping(value = "/token", method = RequestMethod.GET)
    @ResponseBody
    public Map<String, Object> getToken() {

        // 前缀
        String keyPrefix = new SimpleDateFormat("yyyyMMdd").format(new Date()) + "/";
        // file name
        String key = keyPrefix + UUID.randomUUID();


        // 上传策略
        StringMap policy = new StringMap();
        policy.put("scope", "filestoragetest:" + keyPrefix);
        // 匹配前缀
        policy.put("isPrefixalScope", 1);

        // 303 跳转的 URL
        policy.put("returnUrl", hostname + "/upload/uploadStatus/qiniu");
        policy.put("returnBody", "{'key': $(key),'fname': $(fname), 'mimeType': $(mimeType) ,'hash': $(etag)}");

        policy.put("deadline", System.currentTimeMillis() / 1000 + 3600);

        // 回调接口
        policy.put("callbackUrl", hostname + "/upload/qiniucallback");
        // 给回调接口传的数据
        policy.put("callbackBody", "{'key': $(key),'fname': $(fname), 'mimeType': $(mimeType) ,'hash': $(etag)}");
        policy.put("callbackBodyType", "application/json");

        // 文件存储类型。0 为普通存储（默认），1 为低频存储。
        policy.put("fileType", 1);

        Auth auth = Auth.create(accessKey, secretKey);
        String upToken = auth.uploadToken(bucket, key, 5000, policy);

        Map<String, Object> result = new HashMap<>();
        result.put("code", 0);
        result.put("token", upToken);
        result.put("key", key);
        log.info(result.toString());
        return result;

    }

    /**
     * 七牛云上传后回调接口
     */
    @RequestMapping(value = "/qiniucallback", method = RequestMethod.POST, produces = "application/json")
    @ResponseBody
    public ResponseEntity<String> qiniuCallback(HttpServletRequest request) throws IOException {
        // 接收七牛回调过来的内容
        String line = "";
        BufferedReader br = new BufferedReader(new InputStreamReader(request.getInputStream()));
        StringBuilder sb = new StringBuilder();
        while ((line = br.readLine()) != null) {
            sb.append(line);
        }
        // 设置返回给七牛的数据
        JsonObject json = new JsonParser().parse(sb.toString()).getAsJsonObject();
        json.addProperty("success", true);

        // 返回给七牛云的json数据 (七牛云会将此json数据返回给客户端

        log.info(json.toString());

        return new ResponseEntity<String>(json.toString(), HttpStatus.OK);
    }

    /**
     * 七牛云返回客户端结果303跳转地址
     *
     * @return
     */
    @RequestMapping(value = "/uploadStatus/qiniu")
    public ModelAndView qiniuUploadstatus(@RequestParam(value = "upload_ret", required = false) String upload_ret,
                                          @RequestParam(value = "code", required = false) String code,
                                          @RequestParam(value = "error", required = false) String error) throws UnsupportedEncodingException {

        ModelAndView modelAndView = new ModelAndView();

        if (upload_ret != null) {
            // upload_ret 参数值采用URL 安全的 Base64 编码
            // 七牛提供的工具类解密
            byte[] uploadRetBytes = UrlSafeBase64.decode(upload_ret);
            upload_ret = new String(uploadRetBytes);

            JsonObject uploadRet = new JsonParser().parse(upload_ret).getAsJsonObject();
            // pse727wzu.bkt.clouddn.com/20190605/5bd343d4-42c0-469e-985a-c4fd6e4b8eae?e=<>&token=<>

            String fileName = uploadRet.get("key").getAsString();

            String encodedFileName = URLEncoder.encode(fileName, "utf-8");
            String publicUrl = String.format("%s/%s", domainOfBucket, encodedFileName);

            Auth auth = Auth.create(accessKey, secretKey);
            long expireInSeconds = 3600;//1小时，可以自定义链接过期时间

            String finalUrl = auth.privateDownloadUrl(publicUrl, expireInSeconds);

            uploadRet.addProperty("src", finalUrl);

            modelAndView.addObject("uploadRet", uploadRet);

        }

        if (code != null) {
            modelAndView.addObject("code", code);
            modelAndView.addObject("error", error);

        }

        modelAndView.setViewName("qiniuUploadStatus");

        log.info("上传结果303跳转");

        return modelAndView;
    }

}
